package cn.hiapi.publics.api;

import cn.hiapi.basic.ResponseEntity;
import cn.hiapi.basic.controller.BasicController;
import cn.hiapi.basic.exception.BasicException;
import cn.hiapi.basic.jpa.pageable.QueryWrapper;
import cn.hiapi.basic.redis.data.LockConst;
import cn.hiapi.basic.security.TokenGet;
import cn.hiapi.basic.token.Token;
import cn.hiapi.interfaces.DispatchContext;
import cn.hiapi.interfaces.ILockService;
import cn.hiapi.interfaces.config.IConfigService;
import cn.hiapi.shop.service.product.ProductNumService;
import cn.hiapi.shopkeeper.consts.AppConst;
import cn.hiapi.shopkeeper.entity.activity.ActivityHomeAd;
import cn.hiapi.shopkeeper.entity.activity.ActivityLotteryAd;
import cn.hiapi.shopkeeper.entity.activity.ActivityLotteryItem;
import cn.hiapi.shopkeeper.entity.order.ActivityInviteRecord;
import cn.hiapi.shopkeeper.entity.order.ActivityLotteryOrder;
import cn.hiapi.shopkeeper.entity.order.ActivityOrder;
import cn.hiapi.shopkeeper.enums.ActivityType;
import cn.hiapi.shopkeeper.enums.OrderStatus;
import cn.hiapi.shopkeeper.service.Shopkeeper;
import cn.hiapi.shopkeeper.service.activity.ActivityCodeRecordService;
import cn.hiapi.shopkeeper.service.activity.ActivityHomeAdService;
import cn.hiapi.shopkeeper.service.activity.ActivityLotteryAdService;
import cn.hiapi.shopkeeper.service.activity.ActivityLotteryItemService;
import cn.hiapi.shopkeeper.service.order.ActivityInviteRecordService;
import cn.hiapi.shopkeeper.service.order.ActivityLotteryOrderService;
import cn.hiapi.shopkeeper.service.order.ActivityOrderService;
import cn.hiapi.utils.DateUtils;
import cn.hiapi.utils.JsonUtils;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author AdinZ
 * @date 2023/2/5 1:58
 */
@RestController
@RequestMapping("/public/lottery")
public class HomeLotteryController extends BasicController {

    private final DispatchContext dispatchContext;

    public HomeLotteryController(DispatchContext dispatchContext) {
        this.dispatchContext = dispatchContext;
    }


    @ApiOperation(value = "抽奖列表", notes = "抽奖列表", nickname = "AdinZ")
    @GetMapping("")
    public ResponseEntity lottery() {
        List<ActivityHomeAd> adList = this.dispatchContext.getServiceOne(ActivityHomeAdService.class).findList(new QueryWrapper().eq("status", 1), Sort.by(Sort.Direction.DESC, "id"));
        if (adList.isEmpty()) return toSuccess("还没有抽奖活动");
        ActivityHomeAd homeAd = adList.get(0);
        List<ActivityLotteryItem> items = this.dispatchContext.getServiceOne(ActivityLotteryItemService.class).findByAid(homeAd.getId());
        List<JSONObject> collect = items.stream().map(e -> JsonUtils.builder()
                .put("type", e.getType())
                .put("title", e.getTitle())
                .put("thumb", e.getThumb())
                .put("price", e.getPrice())
                .put("lid", e.getType() != 0 ? e.getType() : e.getLid())
                .build()).collect(Collectors.toList());
        Collections.shuffle(collect);
        return toSuccess(JsonUtils.builder()
                .put("items", collect)
                .put("id", homeAd.getId())
                .put("startTime", homeAd.getStartTime())
                .put("endTime", homeAd.getEndTime())
                .build());
    }

    @ApiOperation(value = "抽奖次数", notes = "抽奖次数", nickname = "AdinZ")
    @GetMapping("/count")
    public ResponseEntity lotteryCount() {
        Token<Object> token = TokenGet.get();
        Object count = token == null ? 0L : this.dispatchContext.getServiceOne(ActivityInviteRecordService.class).lotteryCount(token.getFid(), AppConst.ACTIVITY_LOTTERY_HOME);
        return toSuccess("请求成功", count);
    }


    @ApiOperation(value = "立即抽奖",notes = "立即抽奖",nickname = "AdinZ" )
    @GetMapping("/now")
    public ResponseEntity lotteryNow(@RequestParam("id") long aid) {
        Token<Object> token = TokenGet.get();
        if (token == null) return toError("请先登录");


        String lock = LockConst.getLock("lottery-now", token.getFid());
        try {
            this.dispatchContext.getServiceOne(ILockService.class).lockThr(lock);

            ActivityHomeAd homeAd = this.dispatchContext.getServiceOne(ActivityHomeAdService.class).get(aid);
            if (homeAd == null) return toError("活动不存在");
            if (homeAd.getStatus() != 1) return toError("活动没开始或已结束");
            long timeMillis = System.currentTimeMillis();
            if (homeAd.getStartTime() > timeMillis) return toError("活动还没开始");
            if (homeAd.getEndTime() < timeMillis) return toError("活动已结束");

            //关联奖品
            List<ActivityLotteryItem> items = this.dispatchContext.getServiceOne(ActivityLotteryItemService.class).findByAid(homeAd.getId());
            List<Long> collect = items.stream().filter(e -> e.getType() == 0 && e.getLid() > 0).map(ActivityLotteryItem::getLid).collect(Collectors.toList());
            //实际奖品
            List<ActivityLotteryAd> list = this.dispatchContext.getServiceOne(ActivityLotteryAdService.class).findList(new QueryWrapper().in("id", collect).eq("status", 1).eq("payStatus", 1));

            items.forEach(e->{
                Optional<ActivityLotteryAd> optional = list.stream().filter(x -> x.getId().longValue() == e.getLid()).findFirst();
                if(optional.isPresent())e.setStockNum(optional.get().getStockNum());
            });

            List<ActivityLotteryItem> lotteryItems = items.stream()
                    .filter(e -> {
                        long count = this.dispatchContext.getServiceOne(ProductNumService.class).totalByGid(e.getLid(), AppConst.ACTIVITY_SELL_TOTAL);
                        return e.getStockNum() > count;
                    }).collect(Collectors.toList());
            if (lotteryItems.isEmpty()) return toError("奖品已被抽光光了");


            Optional<BigDecimal> totalRate = lotteryItems.stream().map(ActivityLotteryItem::getRate).reduce(BigDecimal::add);
            if(!totalRate.isPresent())return toError("抽奖设置错误");

            //抽奖次数
            List<ActivityInviteRecord> lotteryCount = this.dispatchContext.getServiceOne(ActivityInviteRecordService.class).lotteryList(token.getFid(), AppConst.ACTIVITY_LOTTERY_HOME);
            if (lotteryCount.size() < 1) return toError("没有抽奖次数了");


            JSONObject config = this.dispatchContext.getServiceOne(IConfigService.class).getConfig(AppConst.CONFIG_SHOPKEEPER_CONFIG);
            int lottery_count = JsonUtils.getInt(config, "lottery_count", 0);

            if(lottery_count>0){
                long count = this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class).count(new QueryWrapper()
                        .eq("buyerId", token.getFid())
                        .between("created", DateUtils.todayStart(0).getTime(), DateUtils.todayEnd(0).getTime())
                        .eq("aid", AppConst.ACTIVITY_LOTTERY_HOME)
                );

                if(count>=lottery_count){
                    return toError("今日抽奖次数已用完, 明天再来抽吧");
                }
            }


            boolean lotteryStatus = Shopkeeper.lottery(totalRate.get(), 0);
            ActivityLotteryOrder order = new ActivityLotteryOrder();
            order.setStatus(1);
            order.setBuyerId(token.getFid());
            order.setAid(aid);

            ActivityInviteRecord record = lotteryCount.get(0);
            record.setStatus(1);
            this.dispatchContext.getServiceOne(ActivityInviteRecordService.class).save(record);

            if (!lotteryStatus) {
                this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class).save(order);
                return toResult(202, "奖品与您擦肩而过");
            }

            Map<Long, BigDecimal> map = new ConcurrentHashMap<>();
            for (ActivityLotteryItem e : lotteryItems) {
                map.put(e.getLid(), e.getRate());
            }
            if (map.isEmpty()) throw new BasicException("奖品已经没了");

            long lotteryId = Shopkeeper.lottery(map);

            Optional<ActivityLotteryAd> optional = list.stream().filter(e -> e.getId().longValue() == lotteryId).findFirst();
            ActivityOrder activityOrder = null;
            if (optional.isPresent()) {
                ActivityLotteryAd item = optional.get();
                order.setLotteryState(1);
                order.setTitle(item.getTitle());
                order.setThumb(item.getThumb());
                order.setPrice(item.getPrice());
                order.setAid(item.getId());
                //加一个销量
                this.dispatchContext.getServiceOne(ProductNumService.class).addNumber(item.getId(),   AppConst.ACTIVITY_SELL_TOTAL, 1);
                //创建我的服务
                activityOrder = new ActivityOrder();
                activityOrder.setShopId(item.getShopId());
                activityOrder.setBuyerId(token.getFid());
                activityOrder.setAid(item.getId());
                activityOrder.setTitle(item.getTitle());
                activityOrder.setThumb(item.getThumb());
                activityOrder.setActivityType(ActivityType.LOTTERY_AD);
                activityOrder.setPrice(item.getPrice());
                activityOrder.setCostPrice(item.getPrice());
                activityOrder.setStatusType(0);
                activityOrder.setStatus(OrderStatus.WAIT_USE);
                activityOrder.setFidType(AppConst.ACTIVITY_LOTTERY);
                activityOrder.setUseStart(item.getUseStart());
                activityOrder.setUseEnd(item.getUseEnd());
            }
            this.dispatchContext.getServiceOne(ActivityLotteryOrderService.class).save(order);
            if (activityOrder != null) {
                activityOrder.setFid(order.getId());
                this.dispatchContext.getServiceOne(ActivityOrderService.class).save(activityOrder);
                //抽奖活动添加核销码
                this.dispatchContext.getServiceOne(ActivityCodeRecordService.class).createCode(activityOrder);
                return toSuccess("恭喜你中奖了", JsonUtils.builder()
                        .put("serviceId", activityOrder.getId())
                        .put("title", activityOrder.getTitle())
                        .put("thumb", activityOrder.getThumb())
                        .put("price", activityOrder.getPrice())
                        .put("itemId", optional.get().getId())
                        .build());
            }
            return toResult(202, "奖品与您擦肩而过");
        } finally {
            this.dispatchContext.getServiceOne(ILockService.class).unlock(lock);
        }
    }



}
